package com.slofzx.nuoda.evaluation.version.service.impl;

import com.slofzx.nuoda.common.dto.CompanyDTO;
import com.slofzx.nuoda.common.dto.FileDTO;
import com.slofzx.nuoda.common.entity.MockMultipartFile;
import com.slofzx.nuoda.common.enums.CommonResultEnum;
import com.slofzx.nuoda.common.enums.ServiceResult;
import com.slofzx.nuoda.common.exception.ServiceException;
import com.slofzx.nuoda.common.feign.OfficeClient;
import com.slofzx.nuoda.common.service.FileInfoService;
import com.slofzx.nuoda.common.service.impl.BaseServiceImpl;
import com.slofzx.nuoda.common.vo.CompanyVO;
import com.slofzx.nuoda.common.vo.FileVO;
import com.slofzx.nuoda.common.vo.SysUserVO;
import com.slofzx.nuoda.evaluation.compute.data.dto.ComputeDetailDataDTO;
import com.slofzx.nuoda.evaluation.compute.data.service.ComputeDetailDataService;
import com.slofzx.nuoda.evaluation.compute.data.vo.ComputeDetailDataVO;
import com.slofzx.nuoda.evaluation.project.controller.ReportInfoDTO;
import com.slofzx.nuoda.evaluation.project.dao.PlanInfoDAO;
import com.slofzx.nuoda.evaluation.project.dao.ProjectInfoDAO;
import com.slofzx.nuoda.evaluation.project.dto.PlanInfoDTO;
import com.slofzx.nuoda.evaluation.project.dto.ProjectInfoDTO;
import com.slofzx.nuoda.evaluation.project.dto.ReportInfoVO;
import com.slofzx.nuoda.evaluation.project.entity.PlanInfo;
import com.slofzx.nuoda.evaluation.project.entity.ProjectInfo;
import com.slofzx.nuoda.evaluation.project.enums.FileType;
import com.slofzx.nuoda.evaluation.project.enums.PlanTypeEnum;
import com.slofzx.nuoda.evaluation.project.enums.ProductTypeEnum;
import com.slofzx.nuoda.evaluation.project.observer.BatchObserver;
import com.slofzx.nuoda.evaluation.project.service.ProjectYearDataService;
import com.slofzx.nuoda.evaluation.project.util.BusiUtil;
import com.slofzx.nuoda.evaluation.project.util.CglibUtils;
import com.slofzx.nuoda.evaluation.version.builder.IntegrationReportBuilder;
import com.slofzx.nuoda.evaluation.version.builder.ProjectGasReportBuilder;
import com.slofzx.nuoda.evaluation.version.builder.ProjectReportBuilder;
import com.slofzx.nuoda.evaluation.version.dto.ComputeVersionDTO;
import com.slofzx.nuoda.evaluation.version.dto.CustomFileDTO;
import com.slofzx.nuoda.evaluation.version.service.ComputeVersionService;
import com.slofzx.nuoda.evaluation.version.service.ProjectReportService;
import com.slofzx.nuoda.evaluation.version.vo.ComputeVersionVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 评价信息服务实现类
 *
 * @author nuoda
 * @since 2022-08-11 08:55:59
 */
@Service("projectReportService")
public class ProjectReportServiceImpl extends BaseServiceImpl implements ProjectReportService, BatchObserver {

    @Resource
    private ProjectInfoDAO projectInfoDAO;

    @Autowired
    protected ComputeVersionService computeVersionService;

    @Resource
    protected OfficeClient officeClient;

    @Autowired
    private FileInfoService fileInfoService;

    @Autowired
    private ProjectYearDataService projectYearDataService;

    private static final String UPLOAD_FILE_SOURCE = "report";

    @Autowired
    private ComputeDetailDataService computeDetailDataService;

    @Autowired
    private PlanInfoDAO planInfoDAO;

    @Override
    public List<ReportInfoVO> queryList(ReportInfoDTO dto) {
        Set<String> dataIdSet = null;
        Map<String, PlanInfo> planInfoMap = null;
        // 如果没有项目的筛选条件则获取项目，查询文件则不使用项目ID筛选
        if (StringUtils.isNotEmpty(dto.getBuildOffice()) || Objects.nonNull(dto.getYear()) ||
                StringUtils.isNotEmpty(dto.getPoolType()) || StringUtils.isNotEmpty(dto.getProjectName())) {
            // 查询项目
            final PlanInfoDTO planInfoDTO = new PlanInfoDTO();
            planInfoDTO.setBuildOffice(dto.getBuildOffice());
            planInfoDTO.setPoolType(dto.getPoolType());
            planInfoDTO.setYear(dto.getYear());
            planInfoDTO.setName(dto.getProjectName());
            final List<PlanInfo> planInfos = planInfoDAO.queryList(planInfoDTO);
            if (CollectionUtils.isEmpty(planInfos)) {
                return Collections.EMPTY_LIST;
            }
            planInfoMap = planInfos.stream()
                    .collect(Collectors.toMap(PlanInfo::getId, Function.identity()));

            dataIdSet = planInfoMap.keySet();
        }
        // 组装文件查询DTO
        final FileDTO fileDTO = new FileDTO();
        fileDTO.setTag(dto.getFileType());
        fileDTO.setDataIdSet(dataIdSet);
        fileDTO.setPageSize(dto.getPageSize());
        fileDTO.setPageNo(dto.getPageNo());
        fileDTO.setFileSource(UPLOAD_FILE_SOURCE);
        final List<FileVO> dataList = fileInfoService.findFileList(fileDTO);
        dto.setCount(dataList.size());

        if (CollectionUtils.isEmpty(dataList)) {
            return Collections.EMPTY_LIST;
        }
        // 如果开始没有获取项目列表则重新获取
        if (planInfoMap == null) {
            dataIdSet = dataList.stream().map(FileVO::getSourceId).collect(Collectors.toSet());
            final PlanInfoDTO planInfoDTO = new PlanInfoDTO();
            planInfoDTO.setIdList(dataIdSet);
            final List<PlanInfo> projectInfoVOS = planInfoDAO.queryList(planInfoDTO);
            if (CollectionUtils.isNotEmpty(projectInfoVOS)) {
                planInfoMap = projectInfoVOS.stream()
                        .collect(Collectors.toMap(PlanInfo::getId, Function.identity()));
            }
        }
        // 转换数据
        Map<String, PlanInfo> finalProjectInfoVOMap = planInfoMap;
        return dataList.stream().filter(Objects::nonNull).map(m -> {
            final ReportInfoVO reportInfoVO = new ReportInfoVO();
            CglibUtils.copy(m, reportInfoVO);
            // 根据项目map获取对应的项目名称
            if (MapUtils.isNotEmpty(finalProjectInfoVOMap)) {
                final PlanInfo planInfo = finalProjectInfoVOMap.get(reportInfoVO.getSourceId());
                if(Objects.nonNull(planInfo)) {
                    reportInfoVO.setProjectName(planInfo.getName());
                }
            }
            final FileType fileType = BusiUtil.getEnumById(reportInfoVO.getTag(), FileType.class);
            if (fileType != null) {
                reportInfoVO.setFileType(fileType.getName());
            }
            return reportInfoVO;
        }).collect(Collectors.toList());

    }

    /**
     * 保存上传的报告
     * @param fileDTO
     * @return
     */
    @Override
    @Transactional
    public ServiceResult save(CustomFileDTO fileDTO) {
        final String fileName = fileDTO.getName();
        fileDTO.setName(null);
        delFile(fileDTO,fileName);
//        fileDTO.setFileIdSet(Sets.newHashSet(fileDTO.getId()));
        final int i = fileInfoService.updateFileSource(fileDTO);
        return CommonResultEnum.SUCCESS;
    }

    public ServiceResult deleteReport(String batchId) {
        final FileDTO fileDTO = new FileDTO();
        fileDTO.setTag(FileType.WORD.getId());
        Set<String> dataIdSet = new HashSet<>();
        dataIdSet.add(batchId);
        fileDTO.setDataIdSet(dataIdSet);
        fileDTO.setFileSource(UPLOAD_FILE_SOURCE);
        final List<FileVO> dataList = fileInfoService.findFileList(fileDTO);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (FileVO fileVO : dataList) {
                fileInfoService.deleteFile(fileVO.getId());
            }
        }
        return CommonResultEnum.SUCCESS;
    }


    /**
     * 查询多条数据
     *
     * @param versionId 数据传递类实例对象
     * @param versionId 数据传递类实例对象
     * @return 对象列表
     */
    @Override
    @Transactional
    public ServiceResult createReport(String batchId, String versionId) {
        final String userId = this.getUserId();
        FileVO fileVO = this.newReport(batchId);
        //ComputeVersionVO version =  computeVersionService.queryById(versionId);
        final String tag = "word";
        FileDTO dto = new FileDTO();
        dto.setFileSource(UPLOAD_FILE_SOURCE);
        dto.setDataId(batchId);
        dto.setTag(tag);
        // 如果当前有重复的文件名则删除
        final String name = fileVO.getName();
        delFile(dto, name);
        // fileInfoService.deleteFile(UPLOAD_FILE_SOURCE, batchId);
        final MultipartFile file = new MockMultipartFile(name, name,"text/plain", fileVO.getData());
        dto.setFile(file);
        dto.setUserId(userId);
        dto.setTag(tag);
        fileInfoService.upload(dto);
        logger.info("上传文件完成！");
        return CommonResultEnum.SUCCESS;
    }

    /**
     * 删除同一方案下相同名称的文件
     * @param dto
     * @param name
     */
    private void delFile(FileDTO dto, String name) {
        final FileDTO copy = BusiUtil.deepCopy(dto, FileDTO.class);
        copy.setFileIdSet(null);
        final List<FileVO> fileList = fileInfoService.findFileList(copy);
        if (CollectionUtils.isNotEmpty(fileList)) {
            for (FileVO vo : fileList) {
                if (name.equals(vo.getName())) {
                    fileInfoService.deleteFile(vo.getId());
                }
            }
        }
    }

    public FileVO newReport(String planId) {
        final PlanInfo planInfo = planInfoDAO.selectById(planId);
        // 获取当前任务所有项目
        final ProjectInfoDTO projectInfoDTO = new ProjectInfoDTO();
        projectInfoDTO.setBatchId(planId);
        List<ProjectInfo> projectInfoList = projectInfoDAO.queryList(projectInfoDTO);
        if (CollectionUtils.isEmpty(projectInfoList)) {
            throw new ServiceException("项目不存在，请先导入项目","项目不存在，请先导入项目",null);
        }
        // 获取最终版本的项目和版本id列表
        Set<String> versionIds = new HashSet<>();
        ProjectInfo targetProject = projectInfoList.get(0);
        for (ProjectInfo projectInfo : projectInfoList) {
            if (projectInfo.isUltimate()) {
                targetProject = projectInfo;
            }
            versionIds.add(projectInfo.getComputeId());
        }
        if (CollectionUtils.isEmpty(versionIds)) {
            throw new ServiceException("评价版本不存在，请先评价计算","评价版本不存在，请先评价计算",null);
        }
        // 获取版本列表
        final ComputeVersionDTO versionDTO = new ComputeVersionDTO();
        versionDTO.setFilterIdSet(versionIds);
        List<ComputeVersionVO> versionList =  computeVersionService.queryList(versionDTO);
        if (CollectionUtils.isEmpty(versionList)) {
            throw new ServiceException("评价版本不存在，请先评价计算","评价版本不存在，请先评价计算",null);
        }
        // 获取组织机构
        SysUserVO user =  getUser();
        String officeId = null;
        if(user.getOfficeId()!=null && !user.getOfficeId().equals("") ){
           // officeId = user.getOfficeId();
            officeId = getSubOfficeId(user.getOffice());
        }
        final CompanyDTO dto = new CompanyDTO();
        Set<String> officeIdSet = new HashSet<>();
        officeIdSet.add(officeId);
        officeIdSet.add(targetProject.getBuildOffice());
        dto.setFilterIdSet(officeIdSet);
        final List<CompanyVO> companyVOS = officeClient.queryListInner(dto).getData();
        Map<String, String> officeNameMap = null;
        if (CollectionUtils.isNotEmpty(companyVOS)) {
              officeNameMap = companyVOS.stream().collect(Collectors.toMap(CompanyVO::getId, CompanyVO::getName));
        }
//        CompanyVO companyVO = officeClient.queryById(officeId).getData();
//        if(null==companyVO){
//            companyVO = officeClient.queryById(targetProject.getBuildOffice()).getData();
//        }
        ComputeVersionVO targetVersion = versionList.get(0);
        // 获取最终项目的计算版本
        for (ComputeVersionVO computeVersionVO : versionList) {
            if (computeVersionVO.getProjectId().equals(targetProject.getId())) {
                targetVersion = computeVersionVO;
                break;
            }
        }
        // 获取计算详情列表
        final ComputeDetailDataDTO detailDataDTO = new ComputeDetailDataDTO();
        detailDataDTO.setFilterIdSet(versionIds);
        final List<ComputeDetailDataVO> computeDetailDataVOS = computeDetailDataService.queryList(detailDataDTO);
        // 获取最终版本的计算详情
        ComputeDetailDataVO targetDetailData = computeDetailDataVOS.get(0);
        for (ComputeDetailDataVO detailDataVO : computeDetailDataVOS) {
            if (detailDataVO.getId().equals(targetVersion.getId())) {
                targetDetailData = detailDataVO;
                break;
            }
        }
        if (PlanTypeEnum.POOL.getId().equals(planInfo.getPlanType())) {
            String fileName = planInfo.getName() + "可行性研究报告(经济评价).docx";
            if (ProductTypeEnum.GAS.getId().equals(planInfo.getProductType())) {
                ProjectGasReportBuilder builder = new ProjectGasReportBuilder();
                builder.projectList(projectInfoList)
                        .plan(planInfo)
                        .fileName(fileName)
                        .userOfficeId(officeId)
                        .project(targetProject)
                        .officeNameMap(officeNameMap)
                        .computeVersion(targetVersion)
                        .computeDetailData(targetDetailData);
                return builder.build();
            } else {
                ProjectReportBuilder builder = new ProjectReportBuilder();
                builder.projectList(projectInfoList)
                        .plan(planInfo)
                        .fileName(fileName)
                        .userOfficeId(officeId)
                        .project(targetProject)
                        .officeNameMap(officeNameMap)
                        .computeVersion(targetVersion)
                        .computeVersionList(versionList)
                        .computeDetailData(targetDetailData)
                        .computeDetailDataList(computeDetailDataVOS);
                return builder.build();
            }

        } else {
            String fileName = planInfo.getName() + "一体化研究报告(经济评价).docx";
            IntegrationReportBuilder builder = new IntegrationReportBuilder();
            builder.projectList(projectInfoList)
                    .plan(planInfo)
                    .fileName(fileName)
                    .userOfficeId(officeId)
                    .project(targetProject)
                    .officeNameMap(officeNameMap)
                    .computeVersion(targetVersion)
                    .computeVersionList(versionList)
                    .computeDetailData(targetDetailData)
                    .computeDetailDataList(computeDetailDataVOS);
            return builder.build();
        }


    }

    private String getSubOfficeId(CompanyVO companyVO) {
        String officeId = "0";
        if (companyVO != null) {
            officeId = companyVO.getId();
        }
        if("0".equals(officeId)){
            officeId = null;
            return officeId;
        }
        if (StringUtils.isNotEmpty(officeId)) {

            if (StringUtils.isEmpty(companyVO.getType()) || ( !"sub_office".equals(companyVO.getType()) && !"research".equals(companyVO.getType()))) {
                CompanyVO parentOffice = officeClient.queryById(companyVO.getParentId()).getData();
                if (parentOffice == null) {
                    return officeId;
                }
                return getSubOfficeId(parentOffice);
            }
        }
        return officeId;
    }

    @Override
    public FileVO downloadReport(String planId) {
//        final ComputeVersionVO computeVersion = computeVersionService.queryById(planId);
//        if (Objects.isNull(computeVersion)) {
//            throw new ServiceException("评价版本不存在", null, null);
//        }
        FileDTO dto = new FileDTO();
        dto.setDataId(planId);
        dto.setFileSource(UPLOAD_FILE_SOURCE);
        dto.setTag("word");
        final List<FileVO> fileList = fileInfoService.findFileList(dto);
        FileVO fileVO = null;
        if (CollectionUtils.isNotEmpty(fileList)) {
            final FileVO vo = fileList.get(0);
            if (Objects.nonNull(vo)) {
                fileVO = fileInfoService.getDownloadFile(vo.getId());
            }
        }
        if (Objects.isNull(fileVO)) {
            try {
//                final String projectId = computeVersion.getProjectId();
//                final ProjectInfo projectInfo = projectInfoDAO.selectById(projectId);
                fileVO = this.newReport(planId);
            } catch (Exception e) {
                logger.error("上传评价报告异常！ planId：{}, 错误信息：", planId, e);
                throw new ServiceException("生成报告异常请联系平台管理员", null, null);
            }
        }
        return fileVO;
    }

    @Override
    public String getName() {
        return "project-report";
    }

    /**
     * 删除报告
     * @param batchId
     * @return
     */
    @Override
    public ServiceResult handleBatchDelete(String batchId) {
        // 如果不是方案则不处理删除逻辑
        PlanInfo planInfo = planInfoDAO.selectById(batchId);
        if (planInfo==null) {
            return CommonResultEnum.SUCCESS;
        }
        deleteReport(batchId);
        return CommonResultEnum.SUCCESS;
    }
}
